from django.shortcuts import render
from rest_framework import viewsets, status
from rest_framework.response import Response
from rest_framework.decorators import action
from rest_framework.parsers import MultiPartParser, FormParser
from rest_framework.permissions import AllowAny, IsAuthenticated
from django.shortcuts import get_object_or_404
from django.http import FileResponse, Http404
from .models import Document
from .serializers import DocumentSerializer
import os
import mimetypes
from django.conf import settings
from django.utils.encoding import escape_uri_path
import logging

logger = logging.getLogger(__name__)

# 设置最大文件大小为2GB
MAX_FILE_SIZE = 2 * 1024 * 1024 * 1024  # 2GB in bytes

# Create your views here.

class DocumentViewSet(viewsets.ModelViewSet):
    queryset = Document.objects.all()
    serializer_class = DocumentSerializer
    parser_classes = (MultiPartParser, FormParser)
    
    def get_permissions(self):
        """
        根据不同的操作返回不同的权限
        """
        if self.action in ['list', 'retrieve', 'download']:
            permission_classes = [AllowAny]
        else:
            permission_classes = [IsAuthenticated]
        return [permission() for permission in permission_classes]
    
    def create(self, request, *args, **kwargs):
        """创建文档时检查文件大小"""
        try:
            file_obj = request.FILES.get('file')
            if not file_obj:
                return Response(
                    {'error': '未提供文件'},
                    status=status.HTTP_400_BAD_REQUEST
                )
            
            # 检查文件大小
            if file_obj.size > MAX_FILE_SIZE:
                logger.warning(f"文件大小超过限制: {file_obj.size} bytes > {MAX_FILE_SIZE} bytes")
                return Response(
                    {'error': f'文件大小不能超过2GB，当前文件大小为 {file_obj.size / (1024*1024*1024):.2f}GB'},
                    status=status.HTTP_400_BAD_REQUEST
                )
            
            # 创建文档
            serializer = self.get_serializer(data=request.data)
            serializer.is_valid(raise_exception=True)
            self.perform_create(serializer)
            headers = self.get_success_headers(serializer.data)
            
            logger.info(f"文档上传成功: ID={serializer.instance.id}, 标题={serializer.instance.title}, 大小={file_obj.size / (1024*1024):.2f}MB")
            return Response(
                serializer.data,
                status=status.HTTP_201_CREATED,
                headers=headers
            )
            
        except Exception as e:
            logger.error(f"文件上传失败: {str(e)}")
            return Response(
                {'error': f'上传失败: {str(e)}'},
                status=status.HTTP_500_INTERNAL_SERVER_ERROR
            )
    
    def perform_create(self, serializer):
        """创建文档时记录上传者IP"""
        try:
            x_forwarded_for = self.request.META.get('HTTP_X_FORWARDED_FOR')
            if x_forwarded_for:
                ip = x_forwarded_for.split(',')[0]
            else:
                ip = self.request.META.get('REMOTE_ADDR')
            instance = serializer.save(upload_ip=ip)
            logger.info(f"文档上传成功: ID={instance.id}, 标题={instance.title}, IP={ip}")
        except Exception as e:
            logger.error(f"文档上传失败: {str(e)}")
            raise
    
    @action(detail=True, methods=['get'])
    def download(self, request, pk=None):
        """下载文件并增加下载计数"""
        try:
            document = self.get_object()
            logger.info(f"尝试下载文档: ID={document.id}, 标题={document.title}")
            
            if not document.file:
                logger.warning(f"文档 {document.id} 没有关联文件")
                return Response(
                    {'error': '文件不存在或已被删除'},
                    status=status.HTTP_404_NOT_FOUND
                )
            
            # 获取文件的完整路径
            file_path = document.file.path
            logger.info(f"文件路径: {file_path}")
            
            if not os.path.exists(file_path):
                logger.warning(f"文件不存在: {file_path}")
                return Response(
                    {'error': '文件不存在或已被删除'},
                    status=status.HTTP_404_NOT_FOUND
                )
            
            try:
                # 增加下载计数
                document.download_count += 1
                document.save(update_fields=['download_count'])
                
                # 获取文件的MIME类型
                content_type, _ = mimetypes.guess_type(file_path)
                if not content_type:
                    content_type = 'application/octet-stream'
                
                # 构建文件响应
                response = FileResponse(
                    open(file_path, 'rb'),
                    content_type=content_type
                )
                
                # 设置文件名，处理中文文件名
                filename = os.path.basename(document.file.name)
                encoded_filename = escape_uri_path(filename)
                
                response['Content-Disposition'] = f'attachment; filename="{encoded_filename}"'
                response['Access-Control-Expose-Headers'] = 'Content-Disposition'
                
                logger.info(f"文档 {document.id} 下载成功")
                return response
                
            except IOError as e:
                logger.error(f"文件读取错误: {str(e)}")
                return Response(
                    {'error': '文件读取失败'},
                    status=status.HTTP_500_INTERNAL_SERVER_ERROR
                )
                
        except Http404:
            logger.warning(f"文档不存在: pk={pk}")
            return Response(
                {'error': '文档不存在'},
                status=status.HTTP_404_NOT_FOUND
            )
        except Exception as e:
            logger.error(f"下载错误: {str(e)}")
            return Response(
                {'error': f'下载失败: {str(e)}'},
                status=status.HTTP_500_INTERNAL_SERVER_ERROR
            )
    
    def destroy(self, request, *args, **kwargs):
        """删除文档及其对应的文件"""
        try:
            document = self.get_object()
            logger.info(f"尝试删除文档: ID={document.id}, 标题={document.title}")
            
            if document.file:
                file_path = document.file.path
                if os.path.isfile(file_path):
                    os.remove(file_path)
                    logger.info(f"文件已删除: {file_path}")
            
            document.delete()
            logger.info(f"文档记录已删除: ID={document.id}")
            
            return Response(
                {'message': '文档删除成功'},
                status=status.HTTP_204_NO_CONTENT
            )
        except Exception as e:
            logger.error(f"删除错误: {str(e)}")
            return Response(
                {'error': f'删除失败: {str(e)}'},
                status=status.HTTP_500_INTERNAL_SERVER_ERROR
            )
